// 手写一个防抖、节流函数

// 防抖 触发高频事件n秒后，函数只会执行依次，n秒内事件再次触发，则重新计时

function debounce(fn, wait) {// 非立即执行
	let timer;
	return function(){
		if(timer) clearTimeout(timer)
		timer = setTimeout(() => {
			fn.apply(this, arguments)
		}, wait)
	}
}

function debounce1(fn, wait) {// 立即执行
	let timer;
	return function() {
		if(timer) clearTimeout(timer)
		const immdaitly = !timer
	// 这里 timer 的值在执行完setTimeout时，为一个常量numner,在下一个事件循环的回调中才会被赋值为null，所以，当再次触发函数时，！timer的值为false,是不会触发函数的，只有当等待时间过去之后，当前执行栈中没有任务执行时，才会触发回调队列中的 timer = null 的回调函数
		timer = setTimeout(() => {
			timer = null
		}, wait)
		if(immdaitly) fn.apply(this, arguments)
	}
}

function debounce2(fn, wait, immdaitly) {// 综合以上
	let timer
	return function() {
		if(timer) clearTimeout(timer)
		if(immdaitly) {
			const canNow = !timer
			timer = setTimeout(() => {
				timer = null
			}, wait)
			if(canNow) fn.apply(this, arguments)
		} else {
			timer = setTimeout(() => {
				fn.apply(this, arguments)
			}, wait)
		}
	}
}

// 节流 固定时间内，函数多次触发，只会执行一次，稀释函数的执行频率, 搜索框输入事件

function throttle(fn, wait) { // 时间戳，立即执行
	let last=0
	return function(){
		const currentTime = Date.now()
		// 这里判断剩余的时间是否大于间隔时间，第一次执行必然大于间隔时间，所以会立即执行函数的调用，当再次触发函数时，如果间隔时间太短，当前时间减去上一次触发事件执行函数的时间小于等待的间隔时间时，函数不会执行，所以，这里会根据传入的时间间隔参数 wait,来设定函数触发的执行频率。wait值越大，函数重复执行的间隔时间也就越长。
		if(currentTime - last >= wait) {
			last = currentTime // 将当前时间赋值给开始时间，当再次触发函数时，会比较新的触发函数的当前时间和开始时间，如果两者时间间隔太短，小于等待的间隔时间 wait,则不会触发执行函数，如果大于间隔时间，则重新将当前时间赋值给开始时间，记录下这次执行函数的当前时间，便于下次和新的当前时间比较
			fn.apply(this, arguments)
		}
	}
}

function throttle1(fn, wait) {// 时间戳方法，延迟执行
	let vaild = true
	return function(){
		if(!valid) return
		vaild = false
		setTimeout(() => {
			fn.apply(this, arguments)
			valid = true
		}, wait)
	}
}

function throttle(fn, wait){// 时间戳方法
	let timer = null
	return function(){
		if(!timer) {
			timer = setTimeout(function(){
				fn.apply(this, arguments)
				timer = null
			}, wait)
		}
	}
}

function throttle2(fn, wait) {// 以上两种方式结合
	let timer, startTime = Date.now()
	return function(){
		const currentTime = Date.now()
		const remain = wait - (currentTime - startTime) // 剩余时间
		clearTimeout(timer)
		if(remain <= 0){ // 剩余时间小于0,立即执行函数
			startTime = Date.now()
			fn.apply(this, arguments)
		} else {// 剩余时间大于0，延迟执行函数
			timer = setTimeout(fn, remain)
		}
	}
}